using JGSY.CourseManagement.Domain.Entities;
using JGSY.CourseManagement.Domain.Interfaces;
using JGSY.CourseManagement.Infrastructure.Configuration.JGSY.CourseManagement.Infrastructure.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Microsoft.VisualBasic.ApplicationServices;
using System;
using System.Configuration;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace JGSY.CourseManagement.Infrastructure.Services
{
    /// <summary>
    /// 用户服务，用户登录成功够存储用户信息
    /// </summary>
    public class UserSessionService
    {
        private readonly IConfiguration _configuration;
        /// <summary>
        /// 用户信息
        /// </summary>
        public static UserSessionService UserSessionInfo;
        private readonly IUserSessionRepository _sessionRepository;
        private readonly ILogger<UserSessionService> _logger;
        //private readonly SessionSettings _sessionSettings;

        //public UserSessionService(IOptions<AppSettings> appSettings)
        //{
        //    _sessionSettings = appSettings.Value.Session;
        //}

        //public TimeSpan GetSessionTimeout()
        //{
        //    return TimeSpan.FromMinutes(_sessionSettings.SessionTimeoutMinutes);
        //}

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sessionRepository">用户会话仓储</param>
        /// <param name="logger">日志服务</param>
        public UserSessionService(IUserSessionRepository sessionRepository, UserSessionService _userSessionInfo, ILogger<UserSessionService> logger, IConfiguration configuration)
        {
            _sessionRepository = sessionRepository ?? throw new ArgumentNullException(nameof(sessionRepository));

            _logger = logger ?? throw new ArgumentNullException(nameof(logger));

            int.TryParse(configuration["Session:SessionTimeoutMinutes"],out _defaultSessionTimeoutMinutes);
           
            if (_defaultSessionTimeoutMinutes <= 0)   throw new ArgumentException("会话超时时间必须大于0", nameof(configuration));
          
            _configuration = configuration ?? throw new ArgumentNullException(nameof(_configuration)); ;
          
            UserSessionInfo = _userSessionInfo ;
        }

        /// <summary>
        /// 用户登录成功后创建会话
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="userName">用户名</param>
        /// <param name="expireMinutes">会话过期分钟数</param>
        /// <param name="cancellationToken">取消令牌</param>
        private readonly int _defaultSessionTimeoutMinutes;

        /// <summary>
        /// 用户登录成功后创建会话
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="userName">用户名</param>
        /// <param name="expireMinutes">会话过期分钟数，未指定时使用配置值</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task CreateSessionAsync(string userId, string userName, int? expireMinutes = null, CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrEmpty(userId))
                throw new Exception(nameof(userId) + "用户ID不能为空");
            if (string.IsNullOrWhiteSpace(userName))
                throw new ArgumentException("用户名不能为空", nameof(userName));
            var actualExpireMinutes = expireMinutes ?? _defaultSessionTimeoutMinutes;
            if (actualExpireMinutes <= 0)
                throw new ArgumentOutOfRangeException(nameof(expireMinutes), "过期时间必须大于0");

            try
            {
                var session = new UserSession(userId, userName, Guid.NewGuid().ToString());
                session.ExpireTime = DateTime.UtcNow.AddMinutes(actualExpireMinutes);
                await _sessionRepository.SaveSessionAsync(session, cancellationToken);
                _logger.LogInformation("用户 {UserId} 会话创建成功，过期时间: {ExpireTime}", userId, session.ExpireTime);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户 {UserId} 会话创建失败", userId);
                throw;
            }
        }

        /// <summary>
        /// 获取当前有效的用户会话
        /// </summary>
        /// <param name="userId">可选用户ID，指定时查询特定用户会话</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>用户会话信息或null</returns>
        public async Task<UserSession> GetCurrentSessionAsync(string userId = null, CancellationToken cancellationToken = default)
        {
            try
            {
                return await _sessionRepository.GetCurrentSessionAsync(userId, cancellationToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取当前会话失败");
                throw;
            }
        }


        /// <summary>
        /// 用户登出，使当前会话失效
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task LogoutAsync(string userId, CancellationToken cancellationToken = default)
        {
            if (string.IsNullOrEmpty(userId))
                throw new Exception(nameof(userId) + "用户ID不能为空");
            try
            {
                var session = await _sessionRepository.GetCurrentSessionAsync(userId, cancellationToken);
                if (session != null)
                {
                    session.ExpireTime = DateTime.UtcNow.AddMinutes(-1);
                    await _sessionRepository.InvalidateSessionAsync(session.Id, cancellationToken);
                    _logger.LogInformation("用户 {UserId} 已登出，会话 {SessionId} 已失效", userId, session.Id);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户 {UserId} 登出失败", userId);
                throw;
            }
        }

        public async Task<bool> IsSessionValidAsync(string userId = null, CancellationToken cancellationToken = default)
        {
            try
            {
                var session = await GetCurrentSessionAsync(userId, cancellationToken);
                var isValid = session != null && session.IsValid && session.ExpireTime > DateTime.UtcNow;
                _logger.LogDebug("会话有效性检查: {IsValid}", isValid);
                return isValid;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查会话有效性失败");
                return false;
            }
        }

        /// <summary>
        /// 获取当前用户会话（无参数重载）
        /// </summary>
        public async Task<UserSession> GetCurrentSession()
        {
            return await GetCurrentSessionAsync();
        }

        /// <summary>
        /// 创建用户会话（ ）
        /// </summary>
        /// <param name="id">用户ID（ ）</param>
        /// <param name="userName">用户名</param>
        /// <param name="v">会话过期分钟数</param>
        public async Task CreateSession(string userId, string userName, int v)
        {
            if (string.IsNullOrEmpty(userId))
                throw new Exception(nameof(userId) + "用户ID不能为空");
            if (v <= 0)
                throw new ArgumentOutOfRangeException(nameof(v), "过期时间必须大于0");

            await CreateSessionAsync(userId, userName, v);
        }

        /// <summary>
        /// 清除当前用户会话
        /// </summary>
        public async Task ClearSessionAsync()
        {
            try
            {
                var session = await GetCurrentSessionAsync();
                if (session != null)
                {
                    session.ExpireTime = DateTime.UtcNow.AddMinutes(-1);
                    await _sessionRepository.InvalidateSessionAsync(session.Id, CancellationToken.None);
                    _logger.LogInformation("会话 {SessionId} 已清除", session.Id);
                }
                else
                {
                    _logger.LogWarning("没有找到当前会话，无法清除");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清除会话失败");
                throw;
            }
        }

        public async Task<bool> IsUserAuthenticated()
        {
            UserSession userSession = await GetCurrentSessionAsync();
            if (userSession?.ExpireTime > DateTime.UtcNow)
            {
                return true;
            }
            return false;
        }
    }
}